JSON WEB TOKEN
简称为JWT
,是一个基于JSON
的开放标准,用于通信双方之间传递安全信息的简洁的、URL
安全的表述性声明规范,经常用于身份验证。
JWT
有三部分组成,他们之间用.
分隔,这三部分分别是Header
、Payload
、Signature
,结构如下:
在jwt.io
给予的实例
对于这个例子,其三部分组成分别为
Header
头部,其由两部分组成:声明类型和算法名称,在本例中的Token
类型为jwt
,加密算法为HMAC-SHA256
。将Header
进行BASE64URL
算法编码,即可得到jwt
的第一部分,注意BASE64URL
算法编码与BASE64
编码略有不同,BASE64URL
需要将BASE64
中输出中的+
替换为减号-
,/
替换为_
,而且没有标准的BASE64
填充,把=
去掉。
Payload
有效载荷,其为JWT
的主体,这里可以存放主体数据信息,Payload
包含三个部分,标准中注册的声明、公共的声明、私有的声明。
iss
: jwt
签发者。sub
: jwt
主题。aud
: jwt
接收者。exp
: jwt
过期时间。nbf
: jwt
生效时间。iat
: jwt
的签发时间。jti
: jwt
的唯一身份标识,避免重放攻击。可以在公共声明添加任何信息,我们一般会在里面添加用户信息和业务信息,但是不建议添加敏感信息,因为公共声明部分可以在客户端解密,除非此信息是加密的。
私有声明是服务器和客户端共同定义的声明,同样这里不建议添加敏感信息。
Signature
哈希签名,其通过JWT
中Header
定义的算法,将前两部分数据进行编码后哈希来生成签名,主要是确保数据不会被篡改。
JWT
存储到客户端以后不存在状态或者会话信息,易于拓展。CSRF
攻击,由于使用JWT
一般放置于请求头的Authorization: Bearer ${JWT}
字段中而不使用Cookie
可以有效防止CSRF
攻击。payload
部分可以存储一些其他业务逻辑所必要的非敏感信息,可以减轻服务端压力。JWT
的跨语言支持性,由于json
与加密算法的通用性,在多数语言中都能得到支持。OAuth2
更加轻量,但是其应用场景有所区别,OAuth2
是一种授权框架,通常用于第三方应用授权,JWT
是一种认证协议,用于前后端分离的用户认证以及后端API
的保护。JWT
设置的过期时间到达之前,JWT
始终有效。Payload
是使用BASE64URL
编码的,并没有加密,因此jwt
中在未加密的情况下不能存储敏感数据。JWT
本身包含认证信息,因此一旦信息泄露,任何人都可以获得令牌的所有权限,所以JWT
的有效期不宜设置太长。JWT
,攻击者拥有一个JWT
,可以伪造Header
中的alg
为none
来验证身份,理论上这是符合JWT
规范要求的,而且有些库中都默认实现此验证,所以需要禁用alg
为none
的请求。HMAC
密钥,由于用户可以拿到完整的JWT
,其中就包含加密算法,用户可以根据JWT
中信息爆破密钥,而且整个操作可以本地完成,不需要与服务端交互。